/*
 * @(#)MetalBorders.java	1.30 03/01/23
 *
 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package lookandfeel.Dmetal;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Window;

import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JInternalFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JToolBar;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.AbstractBorder;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.border.MatteBorder;
import javax.swing.plaf.BorderUIResource;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicBorders;
import javax.swing.text.JTextComponent;

/**
 * Factory object that can vend Borders appropriate for the metal L & F.
 * 
 * @author Steve Wilson
 * @version 1.30 01/23/03
 */
@SuppressWarnings( "unused" )
public class MetalBorders
{

	public static class Flush3DBorder extends AbstractBorder implements
			UIResource
	{

		/**
		 * 
		 */
		private static final long serialVersionUID = -1556280725459067227L;

		private static final Insets insets = new Insets(2, 2, 2, 2);

		@Override
		public void paintBorder(Component c, Graphics g, int x, int y, int w,
				int h)
		{
			if (c.isEnabled())
				MetalUtils.drawFlush3DBorder(g, x, y, w, h);
			else MetalUtils.drawDisabledBorder(g, x, y, w, h);
		}

		@Override
		public Insets getBorderInsets(Component c)
		{
			return insets;
		}

		@Override
		public Insets getBorderInsets(Component c, Insets newInsets)
		{
			newInsets.top = insets.top;
			newInsets.left = insets.left;
			newInsets.bottom = insets.bottom;
			newInsets.right = insets.right;
			return newInsets;
		}
	}

	public static class ButtonBorder extends AbstractBorder implements
			UIResource
	{

		/**
		 * 
		 */
		private static final long serialVersionUID = -4285515089279066823L;

		protected static Insets borderInsets = new Insets(3, 3, 3, 3);

		@Override
		public void paintBorder(Component c, Graphics g, int x, int y, int w,
				int h)
		{
			AbstractButton button = (AbstractButton) c;
			ButtonModel model = button.getModel();

			if (model.isEnabled())
			{
				boolean isPressed = model.isPressed() && model.isArmed();
				boolean isDefault = ( ( button instanceof JButton ) && ( (JButton) button )
						.isDefaultButton() );

				if (isPressed && isDefault)
					MetalUtils.drawDefaultButtonPressedBorder(g, x, y, w, h);
				else if (isPressed)
					MetalUtils.drawPressed3DBorder(g, x, y, w, h);
				else if (isDefault)
					MetalUtils.drawDefaultButtonBorder(g, x, y, w, h, false);
				else MetalUtils.drawButtonBorder(g, x, y, w, h, false);
			}
			else MetalUtils.drawDisabledBorder(g, x, y, w - 1, h - 1);
		}

		@Override
		public Insets getBorderInsets(Component c)
		{
			return borderInsets;
		}

		@Override
		public Insets getBorderInsets(Component c, Insets newInsets)
		{
			newInsets.top = borderInsets.top;
			newInsets.left = borderInsets.left;
			newInsets.bottom = borderInsets.bottom;
			newInsets.right = borderInsets.right;
			return newInsets;
		}
	}

	public static class InternalFrameBorder extends AbstractBorder implements
			UIResource
	{

		/**
		 * 
		 */
		private static final long serialVersionUID = -6403521219761654945L;

		private static final Insets insets = new Insets(5, 5, 5, 5);

		private static final int corner = 14;

		@Override
		public void paintBorder(Component c, Graphics g, int x, int y, int w,
				int h)
		{

			Color background;
			Color highlight;
			Color shadow;

			if (( c instanceof JInternalFrame )
					&& ( (JInternalFrame) c ).isSelected())
			{
				background = MetalLookAndFeel.getPrimaryControlDarkShadow();
				highlight = MetalLookAndFeel.getPrimaryControlShadow();
				shadow = MetalLookAndFeel.getPrimaryControlInfo();
			}
			else
			{
				background = MetalLookAndFeel.getControlDarkShadow();
				highlight = MetalLookAndFeel.getControlShadow();
				shadow = MetalLookAndFeel.getControlInfo();
			}

			g.setColor(background);
			// Draw outermost lines
			g.drawLine(1, 0, w - 2, 0);
			g.drawLine(0, 1, 0, h - 2);
			g.drawLine(w - 1, 1, w - 1, h - 2);
			g.drawLine(1, h - 1, w - 2, h - 1);

			// Draw the bulk of the border
			for (int i = 1; i < 5; i++)
				g.drawRect(x + i, y + i, w - ( i * 2 ) - 1, h - ( i * 2 ) - 1);

			if (( c instanceof JInternalFrame )
					&& ( (JInternalFrame) c ).isResizable())
			{
				g.setColor(highlight);
				// Draw the Long highlight lines
				g.drawLine(corner + 1, 3, w - corner, 3);
				g.drawLine(3, corner + 1, 3, h - corner);
				g.drawLine(w - 2, corner + 1, w - 2, h - corner);
				g.drawLine(corner + 1, h - 2, w - corner, h - 2);

				g.setColor(shadow);
				// Draw the Long shadow lines
				g.drawLine(corner, 2, w - corner - 1, 2);
				g.drawLine(2, corner, 2, h - corner - 1);
				g.drawLine(w - 3, corner, w - 3, h - corner - 1);
				g.drawLine(corner, h - 3, w - corner - 1, h - 3);
			}

		}

		@Override
		public Insets getBorderInsets(Component c)
		{
			return insets;
		}

		@Override
		public Insets getBorderInsets(Component c, Insets newInsets)
		{
			newInsets.top = insets.top;
			newInsets.left = insets.left;
			newInsets.bottom = insets.bottom;
			newInsets.right = insets.right;
			return newInsets;
		}
	}

	/**
	 * Border for a Frame.
	 * 
	 * @since 1.4
	 */
	static class FrameBorder extends AbstractBorder implements UIResource
	{

		/**
		 * 
		 */
		private static final long serialVersionUID = -5266838220457863013L;

		private static final Insets insets = new Insets(5, 5, 5, 5);

		private static final int corner = 14;

		@Override
		public void paintBorder(Component c, Graphics g, int x, int y, int w,
				int h)
		{

			Color background;
			Color highlight;
			Color shadow;

			Window window = SwingUtilities.getWindowAncestor(c);
			if (( window != null ) && window.isActive())
			{
				background = MetalLookAndFeel.getPrimaryControlDarkShadow();
				highlight = MetalLookAndFeel.getPrimaryControlShadow();
				shadow = MetalLookAndFeel.getPrimaryControlInfo();
			}
			else
			{
				background = MetalLookAndFeel.getControlDarkShadow();
				highlight = MetalLookAndFeel.getControlShadow();
				shadow = MetalLookAndFeel.getControlInfo();
			}

			g.setColor(background);
			// Draw outermost lines
			g.drawLine(x + 1, y + 0, x + w - 2, y + 0);
			g.drawLine(x + 0, y + 1, x + 0, y + h - 2);
			g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 2);
			g.drawLine(x + 1, y + h - 1, x + w - 2, y + h - 1);

			// Draw the bulk of the border
			for (int i = 1; i < 5; i++)
				g.drawRect(x + i, y + i, w - ( i * 2 ) - 1, h - ( i * 2 ) - 1);

			if (( window instanceof Frame ) && ( (Frame) window ).isResizable())
			{
				g.setColor(highlight);
				// Draw the Long highlight lines
				g.drawLine(corner + 1, 3, w - corner, 3);
				g.drawLine(3, corner + 1, 3, h - corner);
				g.drawLine(w - 2, corner + 1, w - 2, h - corner);
				g.drawLine(corner + 1, h - 2, w - corner, h - 2);

				g.setColor(shadow);
				// Draw the Long shadow lines
				g.drawLine(corner, 2, w - corner - 1, 2);
				g.drawLine(2, corner, 2, h - corner - 1);
				g.drawLine(w - 3, corner, w - 3, h - corner - 1);
				g.drawLine(corner, h - 3, w - corner - 1, h - 3);
			}

		}

		@Override
		public Insets getBorderInsets(Component c)
		{
			return insets;
		}

		@Override
		public Insets getBorderInsets(Component c, Insets newInsets)
		{
			newInsets.top = insets.top;
			newInsets.left = insets.left;
			newInsets.bottom = insets.bottom;
			newInsets.right = insets.right;
			return newInsets;
		}
	}

	/**
	 * Border for a Frame.
	 * 
	 * @since 1.4
	 */
	static class DialogBorder extends AbstractBorder implements UIResource
	{
		/**
		 * 
		 */
		private static final long serialVersionUID = 9027748898435972806L;

		private static final Insets insets = new Insets(5, 5, 5, 5);

		private static final int corner = 14;

		protected Color getActiveBackground()
		{
			return MetalLookAndFeel.getPrimaryControlDarkShadow();
		}

		protected Color getActiveHighlight()
		{
			return MetalLookAndFeel.getPrimaryControlShadow();
		}

		protected Color getActiveShadow()
		{
			return MetalLookAndFeel.getPrimaryControlInfo();
		}

		protected Color getInactiveBackground()
		{
			return MetalLookAndFeel.getControlDarkShadow();
		}

		protected Color getInactiveHighlight()
		{
			return MetalLookAndFeel.getControlShadow();
		}

		protected Color getInactiveShadow()
		{
			return MetalLookAndFeel.getControlInfo();
		}

		@Override
		public void paintBorder(Component c, Graphics g, int x, int y, int w,
				int h)
		{
			Color background;
			Color highlight;
			Color shadow;

			Window window = SwingUtilities.getWindowAncestor(c);
			if (( window != null ) && window.isActive())
			{
				background = getActiveBackground();
				highlight = getActiveHighlight();
				shadow = getActiveShadow();
			}
			else
			{
				background = getInactiveBackground();
				highlight = getInactiveHighlight();
				shadow = getInactiveShadow();
			}

			g.setColor(background);
			// Draw outermost lines
			g.drawLine(x + 1, y + 0, x + w - 2, y + 0);
			g.drawLine(x + 0, y + 1, x + 0, y + h - 2);
			g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 2);
			g.drawLine(x + 1, y + h - 1, x + w - 2, y + h - 1);

			// Draw the bulk of the border
			for (int i = 1; i < 5; i++)
				g.drawRect(x + i, y + i, w - ( i * 2 ) - 1, h - ( i * 2 ) - 1);

			if (( window instanceof Dialog )
					&& ( (Dialog) window ).isResizable())
			{
				g.setColor(highlight);
				// Draw the Long highlight lines
				g.drawLine(corner + 1, 3, w - corner, 3);
				g.drawLine(3, corner + 1, 3, h - corner);
				g.drawLine(w - 2, corner + 1, w - 2, h - corner);
				g.drawLine(corner + 1, h - 2, w - corner, h - 2);

				g.setColor(shadow);
				// Draw the Long shadow lines
				g.drawLine(corner, 2, w - corner - 1, 2);
				g.drawLine(2, corner, 2, h - corner - 1);
				g.drawLine(w - 3, corner, w - 3, h - corner - 1);
				g.drawLine(corner, h - 3, w - corner - 1, h - 3);
			}

		}

		@Override
		public Insets getBorderInsets(Component c)
		{
			return insets;
		}

		@Override
		public Insets getBorderInsets(Component c, Insets newInsets)
		{
			newInsets.top = insets.top;
			newInsets.left = insets.left;
			newInsets.bottom = insets.bottom;
			newInsets.right = insets.right;
			return newInsets;
		}
	}

	/**
	 * Border for an Error Dialog.
	 * 
	 * @since 1.4
	 */
	static class ErrorDialogBorder extends DialogBorder implements UIResource
	{
		/**
		 * 
		 */
		private static final long serialVersionUID = -8222612726660203305L;

		@Override
		protected Color getActiveBackground()
		{
			return UIManager
					.getColor("OptionPane.errorDialog.border.background");
		}
	}

	/**
	 * Border for a QuestionDialog. Also used for a JFileChooser and a
	 * JColorChooser..
	 * 
	 * @since 1.4
	 */
	static class QuestionDialogBorder extends DialogBorder implements
			UIResource
	{
		/**
		 * 
		 */
		private static final long serialVersionUID = 5562944296165898947L;

		@Override
		protected Color getActiveBackground()
		{
			return UIManager
					.getColor("OptionPane.questionDialog.border.background");
		}
	}

	/**
	 * Border for a Warning Dialog.
	 * 
	 * @since 1.4
	 */
	static class WarningDialogBorder extends DialogBorder implements UIResource
	{
		/**
		 * 
		 */
		private static final long serialVersionUID = 7490600612745651118L;

		@Override
		protected Color getActiveBackground()
		{
			return UIManager
					.getColor("OptionPane.warningDialog.border.background");
		}
	}

	/**
	 * Border for a Palette.
	 * 
	 * @since 1.3
	 */
	public static class PaletteBorder extends AbstractBorder implements
			UIResource
	{
		/**
		 * 
		 */
		private static final long serialVersionUID = 7079285019154512728L;

		private static final Insets insets = new Insets(1, 1, 1, 1);

		int titleHeight = 0;

		@Override
		public void paintBorder(Component c, Graphics g, int x, int y, int w,
				int h)
		{

			g.translate(x, y);
			g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
			g.drawLine(0, 1, 0, h - 2);
			g.drawLine(1, h - 1, w - 2, h - 1);
			g.drawLine(w - 1, 1, w - 1, h - 2);
			g.drawLine(1, 0, w - 2, 0);
			g.drawRect(1, 1, w - 3, h - 3);
			g.translate(-x, -y);

		}

		@Override
		public Insets getBorderInsets(Component c)
		{
			return insets;
		}

		@Override
		public Insets getBorderInsets(Component c, Insets newInsets)
		{
			newInsets.top = insets.top;
			newInsets.left = insets.left;
			newInsets.bottom = insets.bottom;
			newInsets.right = insets.right;
			return newInsets;
		}
	}

	public static class OptionDialogBorder extends AbstractBorder implements
			UIResource
	{
		/**
		 * 
		 */
		private static final long serialVersionUID = -7616558283922624969L;

		private static final Insets insets = new Insets(3, 3, 3, 3);

		int titleHeight = 0;

		@Override
		public void paintBorder(Component c, Graphics g, int x, int y, int w,
				int h)
		{

			g.translate(x, y);

			int messageType = JOptionPane.PLAIN_MESSAGE;
			if (c instanceof JInternalFrame)
			{
				Object obj = ( (JInternalFrame) c )
						.getClientProperty("JInternalFrame.messageType");
				if (( obj != null ) && ( obj instanceof Integer ))
					messageType = ( (Integer) obj ).intValue();
			}

			Color borderColor;

			switch (messageType)
			{
				case ( JOptionPane.ERROR_MESSAGE   ):
					borderColor = UIManager
							.getColor("OptionPane.errorDialog.border.background");
					break;
				case ( JOptionPane.QUESTION_MESSAGE   ):
					borderColor = UIManager
							.getColor("OptionPane.questionDialog.border.background");
					break;
				case ( JOptionPane.WARNING_MESSAGE   ):
					borderColor = UIManager
							.getColor("OptionPane.warningDialog.border.background");
					break;
				case ( JOptionPane.INFORMATION_MESSAGE   ):
				case ( JOptionPane.PLAIN_MESSAGE   ):
				default:
					borderColor = MetalLookAndFeel
							.getPrimaryControlDarkShadow();
					break;
			}

			g.setColor(borderColor);

			// Draw outermost lines
			g.drawLine(1, 0, w - 2, 0);
			g.drawLine(0, 1, 0, h - 2);
			g.drawLine(w - 1, 1, w - 1, h - 2);
			g.drawLine(1, h - 1, w - 2, h - 1);

			// Draw the bulk of the border
			for (int i = 1; i < 3; i++)
				g.drawRect(i, i, w - ( i * 2 ) - 1, h - ( i * 2 ) - 1);

			g.translate(-x, -y);

		}

		@Override
		public Insets getBorderInsets(Component c)
		{
			return insets;
		}

		@Override
		public Insets getBorderInsets(Component c, Insets newInsets)
		{
			newInsets.top = insets.top;
			newInsets.left = insets.left;
			newInsets.bottom = insets.bottom;
			newInsets.right = insets.right;
			return newInsets;
		}
	}

	public static class MenuBarBorder extends AbstractBorder implements
			UIResource
	{
		/**
		 * 
		 */
		private static final long serialVersionUID = -3648237697433802339L;

		protected static Insets borderInsets = new Insets(1, 0, 1, 0);

		@Override
		public void paintBorder(Component c, Graphics g, int x, int y, int w,
				int h)
		{
			g.translate(x, y);

			g.setColor(MetalLookAndFeel.getControlShadow());
			g.drawLine(0, h - 1, w, h - 1);

			g.translate(-x, -y);

		}

		@Override
		public Insets getBorderInsets(Component c)
		{
			return borderInsets;
		}

		@Override
		public Insets getBorderInsets(Component c, Insets newInsets)
		{
			newInsets.top = borderInsets.top;
			newInsets.left = borderInsets.left;
			newInsets.bottom = borderInsets.bottom;
			newInsets.right = borderInsets.right;
			return newInsets;
		}
	}

	public static class MenuItemBorder extends AbstractBorder implements
			UIResource
	{
		/**
		 * 
		 */
		private static final long serialVersionUID = -4679933045037112278L;

		protected static Insets borderInsets = new Insets(2, 2, 2, 2);

		@Override
		public void paintBorder(Component c, Graphics g, int x, int y, int w,
				int h)
		{
			JMenuItem b = (JMenuItem) c;
			ButtonModel model = b.getModel();

			g.translate(x, y);

			if (c.getParent() instanceof JMenuBar)
			{
				if (model.isArmed() || model.isSelected())
				{
					g.setColor(MetalLookAndFeel.getControlDarkShadow());
					g.drawLine(0, 0, w - 2, 0);
					g.drawLine(0, 0, 0, h - 1);
					g.drawLine(w - 2, 2, w - 2, h - 1);

					g.setColor(MetalLookAndFeel.getPrimaryControlHighlight());
					g.drawLine(w - 1, 1, w - 1, h - 1);

					g.setColor(MetalLookAndFeel.getMenuBackground());
					g.drawLine(w - 1, 0, w - 1, 0);
				}
			}
			else if (model.isArmed()
					|| ( ( c instanceof JMenu ) && model.isSelected() ))
			{
				g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
				g.drawLine(0, 0, w - 1, 0);

				g.setColor(MetalLookAndFeel.getPrimaryControlHighlight());
				g.drawLine(0, h - 1, w - 1, h - 1);
			}
			else
			{
				g.setColor(MetalLookAndFeel.getPrimaryControlHighlight());
				g.drawLine(0, 0, 0, h - 1);
			}

			g.translate(-x, -y);
		}

		@Override
		public Insets getBorderInsets(Component c)
		{
			return borderInsets;
		}

		@Override
		public Insets getBorderInsets(Component c, Insets newInsets)
		{
			newInsets.top = borderInsets.top;
			newInsets.left = borderInsets.left;
			newInsets.bottom = borderInsets.bottom;
			newInsets.right = borderInsets.right;
			return newInsets;
		}
	}

	public static class PopupMenuBorder extends AbstractBorder implements
			UIResource
	{
		/**
		 * 
		 */
		private static final long serialVersionUID = -7502418530536285340L;

		protected static Insets borderInsets = new Insets(3, 1, 2, 1);

		@Override
		public void paintBorder(Component c, Graphics g, int x, int y, int w,
				int h)
		{
			g.translate(x, y);

			g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
			g.drawRect(0, 0, w - 1, h - 1);

			g.setColor(MetalLookAndFeel.getPrimaryControlHighlight());
			g.drawLine(1, 1, w - 2, 1);
			g.drawLine(1, 2, 1, 2);
			g.drawLine(1, h - 2, 1, h - 2);

			g.translate(-x, -y);

		}

		@Override
		public Insets getBorderInsets(Component c)
		{
			return borderInsets;
		}

		@Override
		public Insets getBorderInsets(Component c, Insets newInsets)
		{
			newInsets.top = borderInsets.top;
			newInsets.left = borderInsets.left;
			newInsets.bottom = borderInsets.bottom;
			newInsets.right = borderInsets.right;
			return newInsets;
		}
	}

	public static class RolloverButtonBorder extends ButtonBorder
	{

		/**
		 * 
		 */
		private static final long serialVersionUID = -516127597133373255L;

		@Override
		public void paintBorder(Component c, Graphics g, int x, int y, int w,
				int h)
		{
			AbstractButton b = (AbstractButton) c;
			ButtonModel model = b.getModel();

			if (model.isRollover() && !( model.isPressed() && !model.isArmed() ))
				super.paintBorder(c, g, x, y, w, h);
		}

	}

	/**
	 * A border which is like a Margin border but it will only honor the margin
	 * if the margin has been explicitly set by the developer.
	 * 
	 * Note: This is identical to the package private class
	 * BasicBorders.RolloverMarginBorder and should probably be consolidated.
	 */
	static class RolloverMarginBorder extends EmptyBorder
	{

		/**
		 * 
		 */
		private static final long serialVersionUID = -6311462079023009120L;

		public RolloverMarginBorder()
		{
			super(3, 3, 3, 3); // hardcoded margin for JLF requirements.
		}

		@Override
		public Insets getBorderInsets(Component c)
		{
			return getBorderInsets(c, new Insets(0, 0, 0, 0));
		}

		@Override
		public Insets getBorderInsets(Component c, Insets insets)
		{
			Insets margin = null;

			if (c instanceof AbstractButton)
				margin = ( (AbstractButton) c ).getMargin();
			if (( margin == null ) || ( margin instanceof UIResource ))
			{
				// default margin so replace
				insets.left = left;
				insets.top = top;
				insets.right = right;
				insets.bottom = bottom;
			}
			else
			{
				// Margin which has been explicitly set by the user.
				insets.left = margin.left;
				insets.top = margin.top;
				insets.right = margin.right;
				insets.bottom = margin.bottom;
			}
			return insets;
		}
	}

	public static class ToolBarBorder extends AbstractBorder implements
			UIResource, SwingConstants
	{
		/**
		 * 
		 */
		private static final long serialVersionUID = -8356103275422634995L;

		protected MetalBumps bumps = new MetalBumps(10, 10, MetalLookAndFeel
				.getControlHighlight(),
				MetalLookAndFeel.getControlDarkShadow(), MetalLookAndFeel
						.getMenuBackground());

		@Override
		public void paintBorder(Component c, Graphics g, int x, int y, int w,
				int h)
		{
			g.translate(x, y);

			if (( (JToolBar) c ).isFloatable())
				if (( (JToolBar) c ).getOrientation() == HORIZONTAL)
				{
					bumps.setBumpArea(10, c.getSize().height - 4);
					if (MetalUtils.isLeftToRight(c))
						bumps.paintIcon(c, g, 2, 2);
					else bumps.paintIcon(c, g, c.getBounds().width - 12, 2);
				}
				else
				{ // vertical
					bumps.setBumpArea(c.getSize().width - 4, 10);
					bumps.paintIcon(c, g, 2, 2);
				}

			g.translate(-x, -y);
		}

		@Override
		public Insets getBorderInsets(Component c)
		{
			return getBorderInsets(c, new Insets(0, 0, 0, 0));
		}

		@Override
		public Insets getBorderInsets(Component c, Insets newInsets)
		{
			newInsets.top = newInsets.left = newInsets.bottom = newInsets.right = 2;

			if (( (JToolBar) c ).isFloatable())
				if (( (JToolBar) c ).getOrientation() == HORIZONTAL)
				{
					if (c.getComponentOrientation().isLeftToRight())
						newInsets.left = 16;
					else newInsets.right = 16;
				}
				else newInsets.top = 16;

			Insets margin = ( (JToolBar) c ).getMargin();

			if (margin != null)
			{
				newInsets.left += margin.left;
				newInsets.top += margin.top;
				newInsets.right += margin.right;
				newInsets.bottom += margin.bottom;
			}

			return newInsets;
		}
	}

	private static Border buttonBorder;

	/**
	 * Returns a border instance for a JButton
	 * 
	 * @since 1.3
	 */
	public static Border getButtonBorder()
	{
		if (buttonBorder == null)
			buttonBorder = new BorderUIResource.CompoundBorderUIResource(
					new MetalBorders.ButtonBorder(),
					new BasicBorders.MarginBorder());
		return buttonBorder;
	}

	private static Border textBorder;

	/**
	 * Returns a border instance for a text component
	 * 
	 * @since 1.3
	 */
	public static Border getTextBorder()
	{
		if (textBorder == null)
			textBorder = new BorderUIResource.CompoundBorderUIResource(
					new MetalBorders.Flush3DBorder(),
					new BasicBorders.MarginBorder());
		return textBorder;
	}

	private static Border textFieldBorder;

	/**
	 * Returns a border instance for a JTextField
	 * 
	 * @since 1.3
	 */
	public static Border getTextFieldBorder()
	{
		if (textFieldBorder == null)
			textFieldBorder = new BorderUIResource.CompoundBorderUIResource(
					new MetalBorders.TextFieldBorder(),
					new BasicBorders.MarginBorder());
		return textFieldBorder;
	}

	public static class TextFieldBorder extends Flush3DBorder
	{

		/**
		 * 
		 */
		private static final long serialVersionUID = 3788190527867090428L;

		@Override
		public void paintBorder(Component c, Graphics g, int x, int y, int w,
				int h)
		{

			if (!( c instanceof JTextComponent ))
			{
				// special case for non-text components (bug ID 4144840)
				if (c.isEnabled())
					MetalUtils.drawFlush3DBorder(g, x, y, w, h);
				else MetalUtils.drawDisabledBorder(g, x, y, w, h);
				return;
			}

			if (c.isEnabled() && ( (JTextComponent) c ).isEditable())
				MetalUtils.drawFlush3DBorder(g, x, y, w, h);
			else MetalUtils.drawDisabledBorder(g, x, y, w, h);

		}
	}

	public static class ScrollPaneBorder extends AbstractBorder implements
			UIResource
	{

		/**
		 * 
		 */
		private static final long serialVersionUID = 7419896963326728522L;

		private static final Insets insets = new Insets(1, 1, 2, 2);

		@Override
		public void paintBorder(Component c, Graphics g, int x, int y, int w,
				int h)
		{

			JScrollPane scroll = (JScrollPane) c;
			JComponent colHeader = scroll.getColumnHeader();
			int colHeaderHeight = 0;
			if (colHeader != null) colHeaderHeight = colHeader.getHeight();
			JComponent rowHeader = scroll.getRowHeader();
			int rowHeaderWidth = 0;
			if (rowHeader != null) rowHeaderWidth = rowHeader.getWidth();

			g.translate(x, y);

			g.setColor(MetalLookAndFeel.getControlDarkShadow());
			g.drawRect(0, 0, w - 2, h - 2);
			g.setColor(MetalLookAndFeel.getControlHighlight());

			g.drawLine(w - 1, 1, w - 1, h - 1);
			g.drawLine(1, h - 1, w - 1, h - 1);

			g.setColor(MetalLookAndFeel.getControl());
			g.drawLine(w - 2, 2 + colHeaderHeight, w - 2, 2 + colHeaderHeight);
			g.drawLine(1 + rowHeaderWidth, h - 2, 1 + rowHeaderWidth, h - 2);

			g.translate(-x, -y);

		}

		@Override
		public Insets getBorderInsets(Component c)
		{
			return insets;
		}
	}

	private static Border toggleButtonBorder;

	/**
	 * Returns a border instance for a JToggleButton
	 * 
	 * @since 1.3
	 */
	public static Border getToggleButtonBorder()
	{
		if (toggleButtonBorder == null)
			toggleButtonBorder = new BorderUIResource.CompoundBorderUIResource(
					new MetalBorders.ToggleButtonBorder(),
					new BasicBorders.MarginBorder());
		return toggleButtonBorder;
	}

	/**
	 * @since 1.3
	 */
	public static class ToggleButtonBorder extends ButtonBorder
	{
		/**
		 * 
		 */
		private static final long serialVersionUID = -6684059392381655281L;

		@Override
		public void paintBorder(Component c, Graphics g, int x, int y, int w,
				int h)
		{
			AbstractButton button = (AbstractButton) c;
			ButtonModel model = button.getModel();

			if (!c.isEnabled())
				MetalUtils.drawDisabledBorder(g, x, y, w - 1, h - 1);
			else if (model.isPressed() && model.isArmed())
				MetalUtils.drawPressed3DBorder(g, x, y, w, h);
			else if (model.isSelected())
				MetalUtils.drawDark3DBorder(g, x, y, w, h);
			else MetalUtils.drawFlush3DBorder(g, x, y, w, h);
		}
	}

	/**
	 * Border for a Table Header
	 * 
	 * @since 1.3
	 */
	public static class TableHeaderBorder extends
			javax.swing.border.AbstractBorder
	{
		/**
		 * 
		 */
		private static final long serialVersionUID = 6462475351450916733L;

		protected Insets editorBorderInsets = new Insets(2, 2, 2, 0);

		@Override
		public void paintBorder(Component c, Graphics g, int x, int y, int w,
				int h)
		{
			g.translate(x, y);

			g.setColor(MetalLookAndFeel.getControlDarkShadow());
			g.drawLine(w - 1, 0, w - 1, h - 1);
			g.drawLine(1, h - 1, w - 1, h - 1);
			g.setColor(MetalLookAndFeel.getControlHighlight());
			g.drawLine(0, 0, w - 2, 0);
			g.drawLine(0, 0, 0, h - 2);

			g.translate(-x, -y);
		}

		@Override
		public Insets getBorderInsets(Component c)
		{
			return editorBorderInsets;
		}
	}

	/**
	 * Returns a border instance for a Desktop Icon
	 * 
	 * @since 1.3
	 */
	public static Border getDesktopIconBorder()
	{
		return new BorderUIResource.CompoundBorderUIResource(new LineBorder(
				MetalLookAndFeel.getControlDarkShadow(), 1), new MatteBorder(2,
				2, 1, 2, MetalLookAndFeel.getControl()));
	}

}
